/*
**
*/
#include "tableview.h"

#include <string>
#include <vector>

#include <QApplication>
#include <QModelIndex>
#include <QMenu>
#include <QAction>
#include <QColor>
#include <QPalette>
#include <QHeaderView>
#include <QAbstractItemModel>
#include <QMouseEvent>
// #include <QDropEvent>
#include <QTextCodec>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
// #include <QMimeData>
#include <QDebug>

#include "FileQt.h"
#include "treemodel.h"
#include "columShowConf.h"
#include "WinViewStyle/myfiledialog.h"

MyTableView::MyTableView(QAbstractItemModel * model,QWidget * parent)
    : QTableView(parent), _currentIndex(QModelIndex())
{
    this->setModel (model);
    win_init();
}

MyTableView::~MyTableView()
{

}

void MyTableView::win_init()
{
    // QFont _font("Courier New", 9);
    // //QFont _font("wenquanyi", 9);
    // _font.setBold(false);
    // this->setFont(_font);
    verticalHeader()->setDefaultSectionSize(36);

    // QPalette pl = this->palette();
    // pl.setColor(QPalette::Base,QColor(240,240,240));
    // pl.setColor(QPalette::Text,QColor(0,0,230));
    // pl.setColor(QPalette::Highlight,QColor(0,230,0));
    // pl.setColor(QPalette::HighlightedText,QColor(255,255,255));
    // // pl.setColor(QPalette::ToolTipBase,QColor(200,200,200));
    // // pl.setColor(QPalette::ToolTipText,QColor(230,230,0));
    // this->setPalette(pl);

    this->setIconSize(QSize(24,24));
    //
    // this->setStyleSheet(
    //     "QScrollBar:vertical{width:16px;border:1px solid rgba(160,160,160,255);margin:0px,0px,0px,0px;padding-top:16px;padding-bottom:16px;}"
    //     "QScrollBar::handle:vertical{width:15px;background:rgba(0,170,255,255);min-height:20;border-radius:5px;}"
    //     "QScrollBar::handle:vertical::disabled{background:rgba(128,128,128,255);}"
    //     "QScrollBar::handle:vertical:hover{width:14px;background:rgba(85,170,0,255);border:1px solid rgba(255,255,255,255);border-radius:5px;}"
    //     "QScrollBar::add-line:vertical{height:16px;subcontrol-position:bottom;border-image:url(:/images/vd_b.png);}"
    //     "QScrollBar::sub-line:vertical{height:16px;subcontrol-position:top;border-image:url(:/images/vu_b.png);}"
    //     "QScrollBar::add-line:vertical:hover{height:16px;subcontrol-position:bottom;border-image:url(:/images/vd_r.png);}"
    //     "QScrollBar::sub-line:vertical:hover{height:16px;subcontrol-position:top;border-image:url(:/images/vu_r.png);}"
    //     "QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:rgba(255,255,255,255);border-radius:5px;}"
    //     "QScrollBar:horizontal{height:16px;border:1px solid rgba(160,160,160,255);margin:0px,0px,0px,0px;padding-left:16px;padding-right:16px;}"
    //     "QScrollBar::handle:horizontal{height:16px;background:rgba(0,170,255,255);min-width:20;border-radius:5px;}"
    //     "QScrollBar::handle:horizontal::disabled{background:rgba(128,128,128,255);}"
    //     "QScrollBar::handle:horizontal:hover{background:rgba(85,170,0,255);border:1px solid rgba(255,255,255,255);border-radius:5px;}"
    //     "QScrollBar::add-line:horizontal{width:16px;subcontrol-position:right;border-image:url(:/images/hr_b.png);}"
    //     "QScrollBar::sub-line:horizontal{width:16px;subcontrol-position:left;border-image:url(:/images/hl_b.png);}"
    //     "QScrollBar::add-line:horizontal:hover{width:16px;subcontrol-position:right;border-image:url(:/images/hr_r.png);}"
    //     "QScrollBar::sub-line:horizontal:hover{width:16px;subcontrol-position:left;border-image:url(:/images/hl_r.png);}"
    //     "QScrollBar::add-page:horizontal,QScrollBar::sub-page:horizontal{background:rgba(255,255,255,255);border-radius:5px;}");
    /*
    **If mouse tracking is switched off, mouse move events only occur
    **if a mouse button is pressed while the mouse is being moved.
    **If mouse tracking is switched on, mouse move events occur even
    **if no mouse button is pressed.
    **If you want to show a tooltip immediately, while the mouse is moving,
    **you must first enable mouse tracking as described above.
    */
    this->setMouseTracking(true);
    this->setTextElideMode(Qt::ElideRight);//...display at the end of the text.
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->setSelectionMode(QAbstractItemView::ExtendedSelection);
    // this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setAlternatingRowColors(true);
    this->setCornerButtonEnabled(true);
    this->setSortingEnabled(true);
}

void MyTableView::defaultContextMenuEvent ( QContextMenuEvent * event )
{
    QMenu menu;
    if(indexAt(event->pos()).isValid()){
        // qDebug()<<indexAt(event->pos()).row()<<","<<indexAt(event->pos()).column();

        QAction *removeRowAction = menu.addAction(tr("removeRow"));
        connect(removeRowAction, SIGNAL(triggered()), this, SLOT(removeRow()));

        // QAction *removeColumnAction = menu.addAction(tr("removeColumn"));
        // connect(removeColumnAction, SIGNAL(triggered()), this, SLOT(removeColumn()));

        // QAction *insertChildAction = menu.addAction(tr("insertChild"));
        // connect(insertChildAction, SIGNAL(triggered()), this, SLOT(insertChild()));
    }

    QAction *insertRowAction = menu.addAction(tr("insertRow"));
    connect(insertRowAction, SIGNAL(triggered()), this, SLOT(insertRow()));

    // QAction *insertColumnAction = menu.addAction(tr("insertColumn"));
    // connect(insertColumnAction, SIGNAL(triggered()), this, SLOT(insertColumn()));

    QAction *importAction = menu.addAction(tr("importFile"));
    connect(importAction, SIGNAL(triggered()), this, SLOT(importFile()));

    QAction *saveAction = menu.addAction(tr("saveFile"));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(saveFile()));


    menu.exec(event->globalPos());

    QTableView::contextMenuEvent(event);
}

// void MyTableView::mousePressEvent ( QMouseEvent * event )
// {
//     startPos = event->pos();
//     QTableView::mousePressEvent(event);
// }

// void MyTableView::mouseReleaseEvent ( QMouseEvent * event )
// {
//     QTableView::mouseReleaseEvent(event);
// }

void MyTableView::mouseMoveEvent ( QMouseEvent * event )
{
    if(!indexAt(event->pos()).isValid()){
        colseExitListWidge();
    }else{
        if (indexAt(event->pos()).column()!=_currentIndex.column())
        {
            colseExitListWidge();
        }
    }
    QTableView::mouseMoveEvent(event);
};

void MyTableView::recover()
{
    /*
    * add exception handing , to prevent deadlocks
    */
    try{
        QAbstractItemModel *model = this->model();
        int count = model->rowCount();
        if(count>0)
            model->removeRows (0,count);
        this->update();
    }catch(QString exception){
        QMessageBox::about(this,tr("exception Error"),exception);
    }
    //qDebug()<<__FUNCTION__<<","<<__LINE__<<"\n";
}

void MyTableView::insertChild()
{
    QModelIndex index = this->selectionModel()->currentIndex();

    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    QVector<QVariant> Data;
    for(int i=0; i<model->columnCount(index);i++)
    	Data << "" ;
    model->insertItemToParent(index,Data/*,model->data(index,Qt::DecorationRole)*/);

    this->selectionModel()->setCurrentIndex(model->index(model->rowCount(index), 0, index),
                                            QItemSelectionModel::ClearAndSelect);
    updateActions();
}

bool MyTableView::insertColumn(QString _name,const QModelIndex &parent, int pos)
{
    if (insertColumn(parent,pos))
    {
        QAbstractItemModel *model = this->model();
        int column = pos;
        if (column<0||column>(model->columnCount(parent)-1))
        {
            column = model->columnCount(parent)-1;
        }
        model->setHeaderData(column, Qt::Horizontal, _name,Qt::EditRole);
        return true;
    }
    return false;
}

bool MyTableView::insertColumn(const QModelIndex &parent, int pos)
{
    QAbstractItemModel *model = this->model();
    // int column = this->selectionModel()->currentIndex().column()+1;
    int column = pos;
    if (column<0||column>model->columnCount(parent))
    {
        column = model->columnCount(parent);
    }
    // Insert a column in the parent item.
    bool changed = model->insertColumn(column, parent);
    if (changed)
        model->setHeaderData(column, Qt::Horizontal, QVariant("[No header]"),
                             Qt::EditRole);

    updateActions();

    return changed;
}

void MyTableView::insertRow()
{
    QModelIndex index = this->selectionModel()->currentIndex().parent();
    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    QVector<QVariant> Data;
    for(int i=0; i<model->columnCount(index);i++)
    	Data << "" ;
    model->insertItemToParent(index,Data/*,
    	QModelIndex()==index?ToIcon():model->data(index,Qt::DecorationRole)*/);

    // qDebug() << model->rowCount(index) << "..1..MyTableView::insertRow....\n";
    this->selectionModel()->setCurrentIndex(model->index(model->rowCount(index), 0, index),
                                            QItemSelectionModel::ClearAndSelect);
    // qDebug() << model->index(model->rowCount(index), 0, index).row() << "..2..MyTableView::insertRow....\n";
    // this->setCurrentIndex(model->index(model->rowCount(index), 0, index));
    // qDebug() << this->selectionModel()->currentIndex().row() << "..3..MyTableView::insertRow....\n";
    updateActions();
}

bool MyTableView::removeColumn(int pos,const QModelIndex &parent)
{
    return removeColumn(parent,pos);
}

bool MyTableView::removeColumn(const QModelIndex &parent, int pos)
{
    QAbstractItemModel *model = this->model();

    int column = pos;
    if (column<0||column>model->columnCount(parent))
    {
        if (this->selectionModel()->currentIndex().isValid())
        {
            column = this->selectionModel()->currentIndex().column();
        }else{
            return false;
        }
    }

    // Insert columns in each child of the parent item.
    bool changed = model->removeColumn(column, parent);

    if (!parent.isValid() && changed)
        updateActions();

    return changed;
}

void MyTableView::removeRow()
{
    QModelIndex index = this->selectionModel()->currentIndex();
    QAbstractItemModel *model = this->model();
    if (model->removeRow(index.row(), index.parent()))
        updateActions();
}

void MyTableView::removeRows()
{
    QAbstractItemModel *model = this->model();
    QModelIndexList _index_slected_list = this->selectionModel()->selectedRows();
    if (_index_slected_list.empty())
    {
        return;
    }
    for (int i = (_index_slected_list.size()-1); i >= 0; i--)
    {
        model->removeRow(_index_slected_list[i].row(), _index_slected_list[i].parent());
    }
    updateActions();
}

void MyTableView::updateActions()
{
    bool hasCurrent = this->selectionModel()->currentIndex().isValid();
    if (hasCurrent) {
        this->closePersistentEditor(this->selectionModel()->currentIndex());
    }
}

void MyTableView::itemClicked(const QModelIndex &index)
{
    if (index.column()==_currentIndex.column()
        &&index.row()!=_currentIndex.row())
    {
        colseExitListWidge();
    }
}

void MyTableView::colseExitListWidge()
{
    QList<QWidget *> widgets = this->findChildren<QWidget *>("widgetname");
    // qDebug() << widgets.size() << "\n";
    for (int i = 0; i < widgets.size(); i++)
    {
        widgets[i]->close();
    }
}

void MyTableView::CheckConfig(QString _str)
{
    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    model->setData(_currentIndex,_str);
    setCurrentIndex(_currentIndex);
}

QVector<QVector<QVariant> > MyTableView::getListComment()
{
    QVector<QVector<QVariant> > _datas;
    QAbstractItemModel *model = this->model();
    int rowCount = model->rowCount();
    int columnCount = model->columnCount();
    for(int i=0; i<rowCount; i++)
    {
        QVector<QVariant> _data;
        for (int j = 0; j < columnCount; j++)
        {
            _data << model->data(model->index(i,j));
        }
        _datas << _data;
    }
    return _datas;
}

void MyTableView::importFile()
{
    importFileFromDir(7);
}

void MyTableView::importFileFromDir(int _dialogf)
{
    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    int count = model->columnCount();
    if (count<1)
    {
        return;
    }
    QStringList _list;
    for (int i = 0; i < count; i++)
    {
        _list << model->headerData(i,Qt::Horizontal).toString();
    }
    qDebug() << "_dialogf = " << _dialogf << "\n";
    ImportConf *_importconf = new ImportConf(_list,this,_dialogf);
    connect(_importconf,SIGNAL(sendConfInfo(ImportConfInfo))
                ,this,SLOT(importAsConf(ImportConfInfo)));
    _importconf->show();
}

void MyTableView::importAsConf(ImportConfInfo inconf)
{
    FileQt *readFile = FileQt::getInstance();
    QVector<QVector<QString> > list;
    if(inconf.file.contains(".xml", Qt::CaseInsensitive))
    {
        readFile->readToVectorXML(inconf.file, inconf.nodes, list,inconf.div);
    }else{
        readFile->readListInfo(list,inconf.file,inconf.div);
    }

    qDebug() << "MyTableView::importAsConf list size = " << list.size() <<"\n";
    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    int count = model->columnCount();

    if (model->rowCount()<(inconf.start+1))
    {
        QVector<QVariant> Data;
        for (int j = 0; j < count; j++)
        {
            Data << "";
        }
        model->insertItemToParent(QModelIndex(),Data);
    }
    int rowCount = model->rowCount();

    for (int i = 0; i < list.size(); i++)
    {
        if (rowCount<=(inconf.start+i))
        {
            QVector<QVariant> Data;
            for (int j = 0; j < count; j++)
            {
                Data << "";
            }
            for (int j = 0; j < list[i].size(); j++)
            {
                if (inconf.list.contains(j))
                {
                    // qDebug() << inconf.list[j].wildcard;
                    Data[inconf.list[j].column] = QString(inconf.list[j].wildcard).arg(list[i][j]);
                }
            }
            model->insertItemToParent(QModelIndex(),Data);
        }else{
            for (int j = 0; j < list[i].size(); j++)
            {
                if (inconf.list.contains(j))
                {
                    // qDebug() << inconf.list[j].wildcard;
                    model->setData(model->index(inconf.start+i,inconf.list[j].column),QString(inconf.list[j].wildcard).arg(list[i][j]));
                }
            }
        }
    }
}

void MyTableView::saveFile()
{
    columCheck(2);
}

void MyTableView::columCheck(int type)
{
    TreeModel *model = qobject_cast<TreeModel *>(this->model());
    int count = model->columnCount();

    QList<ColumnShow> _list;
    for (int i = 0; i < count; i++)
    {
        ColumnShow _ColumnShow;
        _ColumnShow._colDesc = model->headerData(i,Qt::Horizontal).toString();
        _ColumnShow._f = !this->isColumnHidden(i);
        _list.append(_ColumnShow);
        // qDebug() << model->headerData(i,Qt::Horizontal).toString() << "......MyTableView::showColum...\n";
    }
    ColumShowConf *_ColumShowConf = new ColumShowConf(_list,this);
    switch(type)
    {
        case 1:
            connect(_ColumShowConf,SIGNAL(sendColumShow(QMap<int,bool>))
                ,this,SLOT(sendColumShow(QMap<int,bool>)));
            break;
        case 2:
            connect(_ColumShowConf,SIGNAL(sendColumShow(QMap<int,bool>))
                ,this,SLOT(saveAsCheck(QMap<int,bool>)));
            break;
        default:
            break;
    }
    _ColumShowConf->show();
}

void MyTableView::sendColumShow(QMap<int,bool> _list)
{
    QMap<int,bool>::iterator it = _list.begin();
    while(it!=_list.end()){
        //if (it.value())
        //{
        //    this->showColumn(it.key());
        //}else{
        //    this->hideColumn(it.key());
        //}
        this->setColumnHidden(it.key(),!it.value());
        it++;
    }
}

void MyTableView::setSaveFilePath(QString *path)
{
    this->setFilePath(path,0);
}

void MyTableView::saveAsCheck(QMap<int,bool> _list)
{
    QString filespath;
    // this->setFilePath(&filespath);
    setSaveFilePath(&filespath);
    QFile file(filespath);
    if(!this->isCorrectPath(&file))
    {
        return;
    }
    QTextStream data( &file );
    QString strList;

    QAbstractItemModel *model = this->model();
    int rowCount = model->rowCount();
    int columnCount = model->columnCount();

    int MaxCheckColumn = 0;
    for (int j = (columnCount-1); j >= 0; j--)
    {
        if (_list.value(j))
        {
            MaxCheckColumn = j;
            break;
        }
    }
    for(int i=0; i<rowCount; i++)
    {
        strList.clear();
        for (int j = 0; j < columnCount; j++)
        {
            if (!_list.value(j))
            {
                continue;
            }
            strList.append(model->data(model->index(i,j)).toString());
            if (j!=MaxCheckColumn)
            {
                strList.append(QString(","));
            }
        }
        strList.append(QString("\r\n"));
        data << strList;
    }

    file.close();
}

void MyTableView::setFilePath(QString *path,int mode)
{
    // qDebug()<<"MyTableView::setFilePath mode="<<mode<<"\n";
    MyFileDialog *fileDialog = new MyFileDialog(this,mode);

    if(fileDialog->exec() == QDialog::Accepted) {
            *path = fileDialog->selectedFiles()[0];
    }

    if(!(QString(".csv")==path->mid(path->size()-4)&&4<path->size()))
    {
        path->append(QString(".csv"));
    }
}

bool MyTableView::isCorrectPath(QFile *file)
{
    if (!file->open(QFile::WriteOnly | QFile::Truncate)) {
        QMessageBox::warning(this, tr("Save Dialog"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(file->fileName())
                             .arg(file->errorString()));
        return false;
    }else{
        return true;
    }
}